<?php //strip
/**
 * Abstract class for forms for plugin's data.
 *
 * @package odWpPlugin
 * @author Ondrej Donek <ondrejd@gmail.com>
 */
abstract class odWpPlugin_Form_Abstract implements odWpPlugin_Form_Interface
{
	const METHOD_GET  = 'method_get';
	const METHOD_POST = 'method_post';
	
	const TYPE_HIDDEN   = 'type_hidden';
	const TYPE_TEXT     = 'type_text';
	const TYPE_PASSWORD = 'type_password';
	const TYPE_TEXTAREA = 'type_textarea';
	const TYPE_SELECT   = 'type_select';
	const TYPE_CHECKBOX = 'type_checkbox';
	const TYPE_RADIO    = 'type_radio';
	const TYPE_TINYMCE  = 'type_tinymce';
	const TYPE_ARRAY    = 'type_array';
	
	const VALIDATOR_NONE     = 'validator_none';
	const VALIDATOR_NONEMPTY = 'validator_nonempty';
	const VALIDATOR_CHARS    = 'validator_chars';
	const VALIDATOR_INT      = 'validator_int';
	const VALIDATOR_FLOAT    = 'validator_float';
	const VALIDATOR_NUMBER   = 'validator_number';
	const VALIDATOR_EMAIL    = 'validator_email';
	const VALIDATOR_URL      = 'validator_url';
	
	const DECORATOR_SIMPLE = 'decorator_simple';
	const DECORATOR_TABLE  = 'decorator_table';
	
	/** 
	 * @var string Form's name. */
	protected $mName = '';
	
	/** @var string Form's description. */
	protected $mDescription = '';
	
	/** @var string Form's name. */
	protected $mMethod = self::METHOD_POST;
	
	/** @var array Holds array with description of all fields included in the form. */
	protected $mFields = array();
	
	/** @var array Holds array with the current form data. */
	protected $mValues = array();
	
	/** @var string Decorator type. */
	protected $mDecorator = self::DECORATOR_SIMPLE;
	
	/** 
	 * Returns form's description.
	 * 
	 * @return string
	 */
	public function getDescription() 
	{
		return $this->mDescription;
	}
	
	/** 
	 * Returns form's description.
	 * 
	 * @param string $aDescription
	 * @return string
	 */
	public function setDescription($aDescription)
	{
		$this->mDescription = $aDescription;
	}
	
	/**
	 * Set form's value with given name.
	 * 
	 * @param string $aKey
	 * @param string $aValue
	 * @return array
	 */
	public function setValue($aKey, $aValue)
	{
		$this->mValues[$aKey] = $aValue;
	}
	
	/**
	 * Set current form's values.
	 *
	 * @param array $aValues
	 * @return void
	 */
	public function setValues($aValues = array())
	{
    $this->mValues = array_merge($this->mValues, $aValues);
	}
	
	/**
	 * Get current form's values.
	 * 
	 * @return array
	 */
	public function getValues()
	{
		return $this->mValues;
	}
	
	/**
	 * Get form's value with given name.
	 * 
	 * @param string $aKey
   * @param string|null $aDefault
	 * @return mixed
	 */
	public function getValue($aKey, $aDefault = null) 
	{
		return (array_key_exists($aKey, $this->mValues)) ? $this->mValues[$aKey] : $aDefault;
	}
	
	/**
	 * Returns properties of element with given name.
	 * 
	 * @param string $aName
	 * @return array
	 * @throws Exception Whenever element with given name was not found.
	 */
	public function getElementProperties($aName)
	{
		if(!array_key_exists($aName, $this->mFields)) {
			throw new Exception('Element with given name `' . $aName . '` was not found!');
		}
		
		return $this->mFields[$aName];
	}
	
	/**
	 * Set properties of element with given name. If $aOverride is TRUE 
	 * the current properties will be completely overwritten. Properties 
	 * should be defined as such array: array('prop' => 'value', ...).
	 * 
	 * Properties should be defined such as array like this:
	 * <code>
	 * <?php
	 * $properties = array(
	 *   'prop1' => 'value',
	 *   'prop2' => 'value'
	 * );
	 * ?>
	 * </code>
	 * 
	 * @param string $aName
	 * @param array $aProperties Array with properties and its values.
	 * @param boolean $aOverride
	 * @return void
	 * @throws Exception Whenever element with given name was not found.
	 * @todo Validate properties names!
	 * @todo Validate properties values!
	 */
	public function setElementProperties($aName, $aProperties, $aOverride = false)
	{
		if(!array_key_exists($aName, $this->mFields)) {
			throw new Exception('Element with given name `' . $aName . '` was not found!');
		}
		
		if($aOverride === true) {
			$this->mFields[$aName] = $aProperties;
		} else {
			foreach($aProperties as $property_name => $property_value) {
				$this->mFields[$aName][$property_name] = $property_value; 
			}
		}
	}
	
	/**
	 * Returns named property of element with given name. If property 
	 * is not defined NULL will be returned.
	 * 
	 * @param string $aName
	 * @param array $aProperty
	 * @return mixed|null
	 * @throws Exception Whenever element with given name was not found.
	 */
	public function getElementProperty($aName, $aProperty)
	{
		if(!array_key_exists($aName, $this->mFields)) {
			throw new Exception('Element with given name `' . $aName . '` was not found!');
		}
		
		if(!array_key_exists($aProperty, $this->mFields[$aName])) {
			throw new Exception('Property `' . $aProperty . '` is not defined for the element `' . $aName . '`!');
		}
		
		return $this->mFields[$aName][$aProperty];
	}
	
	/**
	 * Set property of element with given name.
	 * 
	 * @param string $aName
	 * @param array $aProperty
	 * @param mixed $aValue
	 * @return void
	 * @throws Exception Whenever element with given name was not found.
	 * @todo Validate given property's name!
	 * @todo Validate given value!               
	 */
	public function setElementProperty($aName, $aProperty, $aValue)
	{
		if(!array_key_exists($aName, $this->mFields)) {
			throw new Exception('Element with given name `' . $aName . '` was not found!');
		}
		
		$aProperty = strtolower($aProperty);
		
		$this->mFields[$aName][$aProperty] = $aValue;
	}
  
} // End of odWpPlugin_Form_Abstract
